package org.owasp.webgoat.session;

import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.regex.Pattern;

import javax.servlet.ServletRequest;

import org.owasp.webgoat.util.HtmlEncoder;

/*******************************************************************************
 * 
 * 
 * This file is part of WebGoat, an Open Web Application Security Project
 * utility. For details, please see http://www.owasp.org/
 * 
 * Copyright (c) 2002 - 2007 Bruce Mayhew
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA 02111-1307, USA.
 * 
 * Getting Source ==============
 * 
 * Source for this application is maintained at code.google.com, a repository
 * for free software projects.
 * 
 * For details, please see http://code.google.com/p/webgoat/
 *
 * @author Jeff Williams <a href="http://www.aspectsecurity.com">Aspect Security</a>
 */
public class ParameterParser
{

    private final static String ALLOWED_CHARACTERS = "$()-?.@!,:;=//+"; // Don't allow #& specifically

    private ServletRequest request;


    /**
     *  Constructs a new ParameterParser to handle the parameters of the given
     *  request.
     *
     *@param  request  the servlet request
     */
    public ParameterParser(ServletRequest request)
    {
	this.request = request;
    }


    /**
     *  Description of the Method
     *
     *@param  s  Description of the Parameter
     *@return    Description of the Return Value
     */
    private String clean(String s)
    {
	StringBuffer clean = new StringBuffer();

	for (int loop = 0; loop < s.length(); loop++)
	{
	    char c = s.charAt(loop);

	    if (Character.isLetterOrDigit(c) || Character.isWhitespace(c)
		    || (ALLOWED_CHARACTERS.indexOf(c) != -1))
	    {
		clean.append(c);
	    }
	    else
	    {
		clean.append('.');
	    }
	}

	return (clean.toString());
    }


    /**
     *  Gets the named parameter value as a boolean
     *
     *@param  name                            the parameter name
     *@return                                 the parameter value as a boolean
     *@exception  ParameterNotFoundException  if the parameter was not found
     */
    public boolean getBooleanParameter(String name)
	    throws ParameterNotFoundException
    {
	return new Boolean(getStringParameter(name)).booleanValue();
    }


    /**
     *  Gets the named parameter value as a boolean, with a default. Returns the
     *  default value if the parameter is not found.
     *
     *@param  name  the parameter name
     *@param  def   the default parameter value
     *@return       the parameter value as a boolean, or the default
     */
    public boolean getBooleanParameter(String name, boolean def)
    {
	try
	{
	    return getBooleanParameter(name);
	}
	catch (Exception e)
	{
	    return def;
	}
    }


    /**
     *  Gets the booleanSubParameter attribute of the ParameterParser object
     *
     *@param  first  Description of the Parameter
     *@param  next   Description of the Parameter
     *@param  def    Description of the Parameter
     *@return        The booleanSubParameter value
     */
    public boolean getBooleanSubParameter(String first, String next, boolean def)
    {
	try
	{
	    return new Boolean(getSubParameter(first, next)).booleanValue();
	}
	catch (Exception e)
	{
	    return def;
	}
    }


    /**
     *  Gets the named parameter value as a byte
     *
     *@param  name                            the parameter name
     *@return                                 the parameter value as a byte
     *@exception  ParameterNotFoundException  if the parameter was not found
     *@exception  NumberFormatException       if the parameter value could not be
     *      converted to a byte
     */
    public byte getByteParameter(String name)
	    throws ParameterNotFoundException, NumberFormatException
    {
	return Byte.parseByte(getStringParameter(name));
    }


    /**
     *  Gets the named parameter value as a byte, with a default. Returns the
     *  default value if the parameter is not found or cannot be converted to a
     *  byte.
     *
     *@param  name  the parameter name
     *@param  def   the default parameter value
     *@return       the parameter value as a byte, or the default
     */
    public byte getByteParameter(String name, byte def)
    {
	try
	{
	    return getByteParameter(name);
	}
	catch (Exception e)
	{
	    return def;
	}
    }


    /**
     *  Gets the named parameter value as a char
     *
     *@param  name                            the parameter name
     *@return                                 the parameter value as a char
     *@exception  ParameterNotFoundException  if the parameter was not found or was
     *      the empty string
     */
    public char getCharParameter(String name) throws ParameterNotFoundException
    {
	String param = getStringParameter(name);

	if (param.length() == 0)
	{
	    throw new ParameterNotFoundException(name + " is empty string");
	}
	else
	{
	    return (param.charAt(0));
	}
    }


    /**
     *  Gets the named parameter value as a char, with a default. Returns the
     *  default value if the parameter is not found.
     *
     *@param  name  the parameter name
     *@param  def   the default parameter value
     *@return       the parameter value as a char, or the default
     */
    public char getCharParameter(String name, char def)
    {
	try
	{
	    return getCharParameter(name);
	}
	catch (Exception e)
	{
	    return def;
	}
    }


    /**
     *  Gets the classNameParameter attribute of the ParameterParser object
     *
     *@param  name  Description of the Parameter
     *@return       The classNameParameter value
     */
    public String getClassNameParameter(String name)
	    throws ParameterNotFoundException
    {
	String p = getStringParameter(name);
	StringTokenizer st = new StringTokenizer(p);

	return (st.nextToken().trim());
    }


    // FIXME: check for [a-zA-Z].([a-zA-Z])*

    /**
     *  Gets the classNameParameter attribute of the ParameterParser object
     *
     *@param  name  Description of the Parameter
     *@param  def   Description of the Parameter
     *@return       The classNameParameter value
     */
    public String getClassNameParameter(String name, String def)
    {
	try
	{
	    return getClassNameParameter(name);
	}
	catch (Exception e)
	{
	    return def;
	}
    }


    /**
     *  Gets the named parameter value as a double
     *
     *@param  name                            the parameter name
     *@return                                 the parameter value as a double
     *@exception  ParameterNotFoundException  if the parameter was not found
     *@exception  NumberFormatException       if the parameter could not be
     *      converted to a double
     */
    public double getDoubleParameter(String name)
	    throws ParameterNotFoundException, NumberFormatException
    {
	return new Double(getStringParameter(name)).doubleValue();
    }


    /**
     *  Gets the named parameter value as a double, with a default. Returns the
     *  default value if the parameter is not found.
     *
     *@param  name  the parameter name
     *@param  def   the default parameter value
     *@return       the parameter value as a double, or the default
     */
    public double getDoubleParameter(String name, double def)
    {
	try
	{
	    return getDoubleParameter(name);
	}
	catch (Exception e)
	{
	    return def;
	}
    }


    /**
     *  Gets the named parameter value as a float
     *
     *@param  name                            the parameter name
     *@return                                 the parameter value as a float
     *@exception  ParameterNotFoundException  if the parameter was not found
     *@exception  NumberFormatException       if the parameter could not be
     *      converted to a float
     */
    public float getFloatParameter(String name)
	    throws ParameterNotFoundException, NumberFormatException
    {
	return new Float(getStringParameter(name)).floatValue();
    }


    /**
     *  Gets the named parameter value as a float, with a default. Returns the
     *  default value if the parameter is not found.
     *
     *@param  name  the parameter name
     *@param  def   the default parameter value
     *@return       the parameter value as a float, or the default
     */
    public float getFloatParameter(String name, float def)
    {
	try
	{
	    return getFloatParameter(name);
	}
	catch (Exception e)
	{
	    return def;
	}
    }


    /**
     *  Gets the named parameter value as an IP String, with a default. Returns the
     *  default value if the parameter is not found or is the empty string.
     *
     *@param  name  the parameter name
     *@param  def   the default parameter value
     *@return       the parameter value as a String, or the default
     */
    public String getIPParameter(String name, String def)
    {
	try
	{
	    return getIPParameter(name);
	}
	catch (Exception e)
	{
	    return def;
	}
    }


    /**
     *  Gets the named parameter value as an IP String
     *
     *@param  name                            the parameter name
     *@return                                 the parameter value as a valid IP
     *      String or an Empty string if invalid
     *@exception  ParameterNotFoundException  if the parameter was not found or was
     *      the empty string
     */
    public String getIPParameter(String name) throws ParameterNotFoundException
    {
	boolean valid = true;
	String[] values = request.getParameterValues(name);
	String value;

	if (values == null)
	{
	    throw new ParameterNotFoundException(name + " not found");
	}
	else if (values[0].length() == 0)
	{
	    throw new ParameterNotFoundException(name + " was empty");
	}
	else
	{
	    // trim illegal characters
	    value = clean(values[0].trim());

	    if (value.indexOf("&") > 0)
	    {
		// truncate additional parameters that follow &
		value = value.substring(0, value.indexOf("&"));
	    }

	    // validate the IP  ex: 124.143.12.254
	    int startIndex = 0;
	    int endIndex = 0;
	    int octetCount = 0;
	    int octetValue;
	    String octet;

	    // if no .'s then it's not an IP
	    if (value.indexOf(".") >= 0)
	    {
		while ((valid == true) && (octetCount < 4))
		{
		    endIndex = value.indexOf(".", startIndex);

		    if (endIndex == -1)
		    {
			endIndex = value.length();
		    }

		    octet = value.substring(startIndex, endIndex);
		    startIndex = endIndex + 1;

		    try
		    {
			octetValue = Integer.parseInt(octet);

			if ((octetValue <= 0) || (octetValue >= 256))
			{
			    valid = false;
			}
		    }
		    catch (Exception e)
		    {
			valid = false;
		    }

		    octetCount++;
		}
	    }
	    else
	    {
		// Not a valid IP
		valid = false;
	    }

	    // Check for any extra garbage. If the last octet was a large value
	    // it would be trapped by the above range check.
	    if (value.length() != endIndex)
	    {
		valid = false;
	    }

	    return valid ? value : null;
	}
    }


    /**
     *  Gets the named parameter value as a int
     *
     *@param  name                            the parameter name
     *@return                                 the parameter value as a int
     *@exception  ParameterNotFoundException  if the parameter was not found
     *@exception  NumberFormatException       if the parameter could not be
     *      converted to a int
     */
    public int getIntParameter(String name) throws ParameterNotFoundException,
	    NumberFormatException
    {
	return Integer.parseInt(getStringParameter(name));
    }


    /**
     *  Gets the named parameter value as a int, with a default. Returns the
     *  default value if the parameter is not found.
     *
     *@param  name  the parameter name
     *@param  def   the default parameter value
     *@return       the parameter value as a int, or the default
     */
    public int getIntParameter(String name, int def)
    {
	try
	{
	    return getIntParameter(name);
	}
	catch (Exception e)
	{
	    return def;
	}
    }


    /**
     *  Gets the named parameter value as a long
     *
     *@param  name                            the parameter name
     *@return                                 the parameter value as a long
     *@exception  ParameterNotFoundException  if the parameter was not found
     *@exception  NumberFormatException       if the parameter could not be
     *      converted to a long
     */
    public long getLongParameter(String name)
	    throws ParameterNotFoundException, NumberFormatException
    {
	return Long.parseLong(getStringParameter(name));
    }


    /**
     *  Gets the named parameter value as a long, with a default. Returns the
     *  default value if the parameter is not found.
     *
     *@param  name  the parameter name
     *@param  def   the default parameter value
     *@return       the parameter value as a long, or the default
     */
    public long getLongParameter(String name, long def)
    {
	try
	{
	    return getLongParameter(name);
	}
	catch (Exception e)
	{
	    return def;
	}
    }


    /**
     *  Determines which of the required parameters were missing from the request.
     *  Returns null if all the parameters are present.
     *
     *@param  requestuired  Description of the Parameter
     *@return               an array of missing parameters, or null if none are
     *      missing
     */
    public String[] getMissingParameters(String[] requestuired)
    {
	Vector missing = new Vector();

	for (int i = 0; i < requestuired.length; i++)
	{
	    String val = getStringParameter(requestuired[i], null);

	    if (val == null)
	    {
		missing.addElement(requestuired[i]);
	    }
	}

	if (missing.size() == 0)
	{
	    return null;
	}
	else
	{
	    String[] ret = new String[missing.size()];
	    missing.copyInto(ret);

	    return ret;
	}
    }


    /**
     *  Gets the parameterNames attribute of the ParameterParser object
     *
     *@return    The parameterNames value
     */
    public Enumeration getParameterNames()
    {
	if (request == null)
	{
	    return (null);
	}

	return request.getParameterNames();
    }


    /**
     *  Gets the parameterValues attribute of the ParameterParser object
     *
     *@param  name  Description of the Parameter
     *@return       The parameterValues value
     */
    public String[] getParameterValues(String name)
    {
	if (request == null)
	{
	    return (null);
	}

	return request.getParameterValues(name);
    }


    /**
     *  Gets the rawParameter attribute of the ParameterParser object
     *
     *@param  name  Description of the Parameter
     *@param  def   Description of the Parameter
     *@return       The rawParameter value
     */
    public String getRawParameter(String name, String def)
    {
	try
	{
	    return getRawParameter(name);
	}
	catch (Exception e)
	{
	    return def;
	}
    }


    /**
     *  Gets the rawParameter attribute of the ParameterParser object
     *
     *@param  name                            Description of the Parameter
     *@return                                 The rawParameter value
     *@exception  ParameterNotFoundException  Description of the Exception
     */
    public String getRawParameter(String name)
	    throws ParameterNotFoundException
    {
	String[] values = request.getParameterValues(name);

	if (values == null)
	{
	    throw new ParameterNotFoundException(name + " not found");
	}
	else if (values[0].length() == 0)
	{
	    throw new ParameterNotFoundException(name + " was empty");
	}

	return (values[0]);
    }


    /**
     *  Gets the named parameter value as a short
     *
     *@param  name                            the parameter name
     *@return                                 the parameter value as a short
     *@exception  ParameterNotFoundException  if the parameter was not found
     *@exception  NumberFormatException       if the parameter could not be
     *      converted to a short
     */
    public short getShortParameter(String name)
	    throws ParameterNotFoundException, NumberFormatException
    {
	return Short.parseShort(getStringParameter(name));
    }


    /**
     *  Gets the named parameter value as a short, with a default. Returns the
     *  default value if the parameter is not found.
     *
     *@param  name  the parameter name
     *@param  def   the default parameter value
     *@return       the parameter value as a short, or the default
     */
    public short getShortParameter(String name, short def)
    {
	try
	{
	    return getShortParameter(name);
	}
	catch (Exception e)
	{
	    return def;
	}
    }


    /**
     *  Gets the named parameter value as a String
     *
     *@param  name                            the parameter name
     *@return                                 the parameter value as a String
     *@exception  ParameterNotFoundException  if the parameter was not found or was
     *      the empty string
     */
    public String getStringParameter(String name)
	    throws ParameterNotFoundException
    {
	String[] values = request.getParameterValues(name);
	String value;

	if (values == null)
	{
	    throw new ParameterNotFoundException(name + " not found");
	}
	else if (values[0].length() == 0)
	{
	    throw new ParameterNotFoundException(name + " was empty");
	}
	else
	{
	    // trim illegal characters
	    value = clean(values[0].trim());

	    if (value.indexOf("&") > 0)
	    {
		// truncate additional parameters that follow &
		value = value.substring(0, value.indexOf("&"));
	    }

	    return value;
	}
    }


    /**
     *  Gets the named parameter value as a String, with a default. Returns the
     *  default value if the parameter is not found or is the empty string.
     *
     *@param  name  the parameter name
     *@param  def   the default parameter value
     *@return       the parameter value as a String, or the default
     */
    public String getStringParameter(String name, String def)
    {
	try
	{
	    return getStringParameter(name);
	}
	catch (Exception e)
	{
	    return def;
	}
    }


    /**
     *  Gets the subParameter attribute of the ParameterParser object
     *
     *@param  first  Description of the Parameter
     *@param  next   Description of the Parameter
     *@param  def    Description of the Parameter
     *@return        The subParameter value
     */
    public String getSubParameter(String first, String next, String def)
    {
	try
	{
	    return getSubParameter(first, next);
	}
	catch (Exception e)
	{
	    return def;
	}
    }


    /**
     *  Gets the parameter named 'next' following the parameter 'first'. Presumes
     *  the structure: first=firstvalue&next=nextValue
     *
     *@param  first                           Description of the Parameter
     *@param  next                            Description of the Parameter
     *@return                                 The subParameter value
     *@exception  ParameterNotFoundException  Description of the Exception
     */
    public String getSubParameter(String first, String next)
	    throws ParameterNotFoundException
    {
	String[] values = request.getParameterValues(first);
	String value;

	if (values == null)
	{
	    throw new ParameterNotFoundException(first + " not found");
	}
	else if (values[0].length() == 0)
	{
	    throw new ParameterNotFoundException(first + " was empty");
	}
	else
	{
	    value = clean(values[0].trim());

	    int idx = value.indexOf("&") + 1;

	    // index of first char of first sub-param name
	    if (idx == 0)
	    {
		throw new ParameterNotFoundException("No subparameter key");
	    }

	    value = value.substring(idx);

	    //System.out.println("= = = = = =Parameter parser looking for " + next + " in " + value );
	    int nextValueIndex = value.indexOf(next + "=");

	    //System.out.println("= = = = = =Parameter parser nextValueIndex = " + nextValueIndex );
	    if (nextValueIndex < 0)
	    {
		throw new ParameterNotFoundException("No subparameter value");
	    }

	    nextValueIndex += (next.length() + 1);

	    if (nextValueIndex >= 0)
	    {
		value = value.substring(nextValueIndex);
	    }
	    else
	    {
		throw new ParameterNotFoundException(next + " not found");
	    }
	}

	if (value.indexOf("&") > 0)
	{
	    // truncate additional parameters that follow &
	    value = value.substring(0, value.indexOf("&"));
	}

	//System.out.println("=-=-=-=-=ParameterParser returning value " + value );
	return value;
    }


    /**
     *  Gets the wordParameter attribute of the ParameterParser object
     *
     *@param  name  Description of the Parameter
     *@return       The wordParameter value
     */
    public String getWordParameter(String name)
	    throws ParameterNotFoundException
    {
	String p = getStringParameter(name);
	StringTokenizer st = new StringTokenizer(p);

	return (st.nextToken().trim());
    }


    // FIXME: check for [a-zA-Z]

    /**
     *  Gets the wordParameter attribute of the ParameterParser object
     *
     *@param  name  Description of the Parameter
     *@param  def   Description of the Parameter
     *@return       The wordParameter value
     */
    public String getWordParameter(String name, String def)
    {
	try
	{
	    return getWordParameter(name);
	}
	catch (Exception e)
	{
	    return def;
	}
    }


    /**
     * Gets the specified parameter from the request and validates it against the provided regular expression. 
     * If the regular expression check fails, the default value is returned instead. 
     *
     *@param  name  		The name of the parameter to retrieve from the request.
     *@param  def   		The default value of the parameter.
     *@param  regexpattern	The precompiled regular expression to be used to validate the parameter.
     *@return       The validated parameter value, or the default value if validation failed.
     */
    private String getRegexParameter(String name, String def,
	    Pattern regexpattern) throws ValidationException
    {
	try
	{
	    return getRegexParameter(name, regexpattern);
	}
	catch (Exception e)
	{
	    //System.out.println("Exception occured in defined pattern match");
	    //e.printStackTrace();
	    return def;
	}
    }


    /**
     * Gets the specified parameter from the request and validates it against the provided regular expression. 
     * If the regular expression check fails, the default value is returned instead. 
     *
     *@param  name  		The name of the parameter to retrieve from the request.
     *@param  def   		The default value of the parameter.
     *@param  regexpattern	The precompiled regular expression to be used to validate the parameter.
     *@return       The validated parameter value, or the default value if validation failed.
     */
    private String getRegexParameter(String name, Pattern regexpattern)
	    throws ParameterNotFoundException, ValidationException
    {
	String param = getStringParameter(name);

	if (regexpattern.matcher(param).matches())
	{
	    return param;
	}
	else
	{
	    //System.out.println(param + " didn't match defined pattern.");
	    throw new ValidationException(name + " contained an invalid value");
	}
    }


    public String getStrictAlphaParameter(String name, int maxLength)
	    throws ParameterNotFoundException, ValidationException
    {
	String alphaRegEx = "^[a-zA-Z\\s]{0," + maxLength + "}$";
	Pattern alphaPattern = Pattern.compile(alphaRegEx);

	return getRegexParameter(name, alphaPattern);
    }


    public String getStrictNumericParameter(String name, int maxLength)
	    throws ParameterNotFoundException, ValidationException
    {
	String numericRegEx = "^\\d{0," + maxLength + "}$";
	Pattern numericPattern = Pattern.compile(numericRegEx);

	return getRegexParameter(name, numericPattern);
    }

    private static final String SSNREGEX = "^\\d{3}-\\d{2}-\\d{4}$";

    private static final Pattern Ssnpattern = Pattern.compile(SSNREGEX);


    public String getSsnParameter(String name)
	    throws ParameterNotFoundException, ValidationException
    {
	return getRegexParameter(name, Ssnpattern);
    }

    // Validates format for major brands of credit card.
    //private static final String CCNREGEX = "^(?:(?<Visa>4\\d{3})|(?<Mastercard>5[1-5]\\d{2})|(?<Discover>6011)|(?<DinersClub>(?:3[68]\\d{2})|(?:30[0-5]\\d))|(?<AmericanExpress>3[47]\\d{2}))([ -]?)(?(DinersClub)(?:\\d{6}\\1\\d{4})|(?(AmericanExpress)(?:\\d{6}\\1\\d{5})|(?:\\d{4}\\1\\d{4}\\1\\d{4})))$";
    private static final String CCNREGEX = "^\\d{16}$";

    private static final Pattern Ccnpattern = Pattern.compile(CCNREGEX);


    public String getCcnParameter(String name)
	    throws ParameterNotFoundException, ValidationException
    {
	return getRegexParameter(name, Ccnpattern);
    }

    private static final String ZIPREGEX = "^\\d{5}(-\\d{4})?$";

    private static final Pattern Zippattern = Pattern.compile(ZIPREGEX);


    public String getZipParameter(String name)
	    throws ParameterNotFoundException, ValidationException
    {
	return getZipParameter(name, null);
    }


    public String getZipParameter(String name, String def)
	    throws ValidationException
    {
	return getRegexParameter(name, def, Zippattern);
    }

    private static final String PHONEREGEX = "^\\(?[\\d]{3}\\)?[\\s-]?[\\d]{3}[\\s-]?[\\d]{4}$";

    // Or this more forgiving pattern:
    //private static final String PHONEREGEX = "^([\\-()+ 0-9x])+$";
    private static final Pattern phonepattern = Pattern.compile(PHONEREGEX);


    public String getPhoneParameter(String name)
	    throws ParameterNotFoundException, ValidationException
    {
	return getPhoneParameter(name, null);
    }


    public String getPhoneParameter(String name, String def)
	    throws ValidationException
    {
	return getRegexParameter(name, def, phonepattern);
    }

    private static final String EMAILREGEX = "^[\\w-]+(?:\\.[\\w-]+)*@(?:[\\w-]+\\.)+[a-zA-Z]{2,7}$";

    private static final Pattern emailpattern = Pattern.compile(EMAILREGEX);


    public String getEMailParameter(String name)
	    throws ParameterNotFoundException, ValidationException
    {
	return getEMailParameter(name, null);
    }


    public String getEMailParameter(String name, String def)
	    throws ValidationException
    {
	return getRegexParameter(name, def, emailpattern);
    }

    private static final String DATEREGEX = "([\\/ .,:0-9a-zA-Z])+$";

    private static final Pattern datepattern = Pattern.compile(DATEREGEX);


    public String getDateParameter(String name)
	    throws ParameterNotFoundException, ValidationException
    {
	return getDateParameter(name, null);
    }


    public String getDateParameter(String name, String def)
	    throws ValidationException
    {
	return getRegexParameter(name, def, datepattern);
    }

    private static final String URLREGEX = "^(((https?)://)([-()_.!~*';/?:@&=+$,A-Za-z0-9])+)([).!';/?:,][[:blank:]])?$";

    private static final Pattern URLpattern = Pattern.compile(URLREGEX);


    public String getURLParameter(String name)
	    throws ParameterNotFoundException, ValidationException
    {
	return getURLParameter(name, null);
    }


    public String getURLParameter(String name, String def)
	    throws ValidationException
    {
	return getRegexParameter(name, def, URLpattern);
    }


    protected static String htmlEncode(String s)
    {
	return HtmlEncoder.encode(s);
    }


    /**
     *  Description of the Method
     *
     *@return    Description of the Return Value
     */
    public String toString()
    {
	StringBuffer s = new StringBuffer("[");
	Enumeration e = getParameterNames();

	while (e.hasMoreElements())
	{
	    String key = (String) e.nextElement();
	    s.append(key + "=" + getParameterValues(key)[0]);

	    // FIXME: Other values?
	    if (e.hasMoreElements())
	    {
		s.append(",");
	    }
	}

	s.append("]");

	return (s.toString());
    }


    /**
     *  Description of the Method
     *
     *@param  request  Description of the Parameter
     */
    public void update(ServletRequest request)
    {
	this.request = request;
    }
}
